package com.dongbao.dialog;

import cn.hutool.json.JSONUtil;
import com.dongbao.core.config.MyState;
import com.dongbao.core.export.ExportExcelUtil;
import com.dongbao.core.export.bean.ExportTableBean;
import com.dongbao.entity.AwardedInfo;
import com.dongbao.entity.CodeScoreInfo;
import com.dongbao.entity.PluginModueExamInfo;
import com.dongbao.entity.ScanResult;
import com.dongbao.util.*;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.twelvemonkeys.io.WriterOutputStream;
import org.codehaus.groovy.runtime.StringBufferWriter;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

public class DHGToolWindow  extends SimpleToolWindowPanel implements HyperlinkListener {

    private static final Logger LOGGER = Logger.getInstance(DHGToolWindow.class);

    private JPanel panel;
    private JPanel writeRulePlan;
    private JPanel codeErrorPlan;
    private JTabbedPane mainTab;
    private JTable codeErrorTable;
    private JButton export;
    private JButton openUrlBtn;
    private JPanel moduleProjectPlan;
    private JTable pluginModuleTable;
    private JTextField startIpInput;
    private JTextField endIpInput;
    private JTextField portInput;
    private JButton execScanBtn;
    private JTable ipResultTable;
    private JEditorPane casePlan;

    private Project myProject;

    private List<AwardedInfo> deductions;

    private List<PluginModueExamInfo> pluginModuledeductions;

    private final Object[] columnNames = {"问题编号","类名","方法名","扣除分值","规则类型","错误信息"};

    private final Object[] pluginColumnNames = {"模块名","文件名","错误信息","改进建议"};

    private final Object[] ipColumnNames = {"IP","端口","状态","DHG服务","版本服务"};

    public DHGToolWindow(Project project, ToolWindow toolWindow) {
        super(true, false);
        this.setContent(panel);
        this.myProject = project;
        initCodeRult();
        initPluginModule();
    }

    public void initPluginModule(){
        /* 渲染错误数据展示的表格 */
        Object[][] rowData = { };
        TableModel dataModel = new DefaultTableModel(rowData,pluginColumnNames);
        pluginModuleTable.setModel(dataModel);
        //允许表格内容编辑
//        codeErrorTable.setEnabled(false);
        pluginModuleTable.addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e){
                if(e.getClickCount() == 1){
                    //实现双击 {
                    int row =((JTable)e.getSource()).rowAtPoint(e.getPoint()); //获得行位置
                    int  col=((JTable)e.getSource()).columnAtPoint(e.getPoint());
                    //获得列位置
                    TableModel tbModel = codeErrorTable.getModel();
//                    Object cellVal=(String)(tbModel.getValueAt(row,col));
                    // 获得点击单元格数据
                    PluginModueExamInfo modueExamInfo = pluginModuledeductions.get(row);
                    FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
                    FileEditor[] fileEditors = fileEditorManager.openFile(modueExamInfo.getVirtualFile(), true);
                    Integer lineNumber = modueExamInfo.getStartLine();
                    IdeaApiUtil.gotoLine(lineNumber,myProject);
                }
            }
        });
    }

    public void initCodeRult(){
        /* 渲染错误数据展示的表格 */
        Object[][] rowData = {
        };
        TableModel dataModel = new DefaultTableModel(rowData,columnNames);
        codeErrorTable.setModel(dataModel);
        //允许表格内容编辑
//        codeErrorTable.setEnabled(false);
        codeErrorTable.addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e){
                if(e.getClickCount() == 1){
                    //实现双击 {
                    int row =((JTable)e.getSource()).rowAtPoint(e.getPoint()); //获得行位置
                    int  col=((JTable)e.getSource()).columnAtPoint(e.getPoint());
                    //获得列位置
                    TableModel tbModel = codeErrorTable.getModel();
//                    Object cellVal=(String)(tbModel.getValueAt(row,col));
                    // 获得点击单元格数据
                    AwardedInfo awardedInfo = deductions.get(row);
                    FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
                    FileEditor[] fileEditors = fileEditorManager.openFile(awardedInfo.getVirtualFile(), true);

                    Integer lineNumber = awardedInfo.getBeginline();
                    if(awardedInfo.getType()==2){
                        lineNumber = awardedInfo.getBeginline()+1;
                    }
                    IdeaApiUtil.gotoLine(lineNumber,myProject);
                    errorCaseShow(awardedInfo);
                }
            }
        });

        /* 打开DHG规范说明URL地址 */
        openUrlBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 调用电脑浏览器打开DHG代码规范的页面
                String url = MyState.getInstance().getConfig().getGitUrlPath() + "/java/hcm/db-file/blob/develop/%E8%A7%84%E8%8C%83/%E4%BB%A3%E7%A0%81%E7%BC%96%E5%86%99%E8%A7%84%E8%8C%83/%E4%BB%A3%E7%A0%81%E7%BC%96%E5%86%99%E8%A7%84%E8%8C%83V1.0.12-210528_1409.md";
                try {
                    Runtime.getRuntime().exec("cmd /c start " + url);//启用cmd运行默认浏览器
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                LOGGER.info("调用电脑浏览器打开DHG代码规范的页面");
            }
        });
        /* 导出当前的代码错误报告 */
        export.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                exportErrorExcel();
            }
        });
        /* 开始执行扫描IP段服务 */
        execScanBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ProgressManager.getInstance().run(new Task.Backgroundable(myProject,"DHG服务检索中,请稍后", false) {
                    @Override
                    public void run(@NotNull ProgressIndicator indicator) {
                        ApplicationManager.getApplication().runReadAction(
                                () -> {
                                    execScanService(indicator);
                                    LOGGER.info("开始执行扫描IP段服务");
                                }
                        );
                    }
                });
            }
        });
    }

    /**
     * 切换错误案例的HTML
     * */
    public void errorCaseShow(AwardedInfo awardedInfo){
        try{
            //在右侧小面板显示出代码的正确与错误的代码示例
            String batSourcePath = null;
            String sonPath = "case/" + awardedInfo.getCode() + ".html";
            URL resource = DHGToolWindow.class.getClassLoader().getResource(sonPath);
            if(resource!=null){
                batSourcePath = resource.getPath().replace("file:/","");
            }else{
                sonPath = "case/404.html";
                batSourcePath = DHGToolWindow.class.getClassLoader().getResource("case/404.html").getPath().replace("file:/","");
            }

            //从jar包中将案例HTML复制到临时的缓存目录
            StorageConfig config = MyState.getInstance().getConfig();
            String savePath = config.getCachePath();
            if(!Paths.get(savePath,sonPath).toFile().exists()){
                FileUtil.copyMainfest(new File(batSourcePath.substring(0,batSourcePath.indexOf("!"))),sonPath, Paths.get(savePath,sonPath).toFile());
            }
            //设置是显示网页 html 文件,可选项
            casePlan.setContentType("text/html");
            //设置成只读，如果是可编辑，你会看到显示的样子也是不一样的，true显示界面
            casePlan.setEditable(false);
            //要能响应网页中的链接，则必须加上超链监听器
            casePlan.addHyperlinkListener(this);
            casePlan.setPage("file:\\" + savePath + File.separator + sonPath);
//            Writer pageOut = new OutputStreamWriter(content, "utf-8");
//            casePlan.write(pageOut);
        }catch (Exception ex){
            LOGGER.info("读取页面 " + awardedInfo.getCode() + "错误案例页面出错：" + ex.getMessage());
        }
    }

    /**
     * 导出代码检测问题结果和 Excel
     * */
    public void exportErrorExcel(){
        //打开弹窗选择保存位置
        FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, false , false, false, false);
        VirtualFile[] virtualFiles = FileChooser.chooseFiles(descriptor,myProject, null);
        if(virtualFiles.length==0){
            return ;
        }
        try{
            File exportFile = new File(virtualFiles[0].getPath(),System.currentTimeMillis()+".xlsx");
            FileOutputStream out = new FileOutputStream(exportFile);
            //开始处理封装Excel
            ExportTableBean exportTableBean = new ExportTableBean();
            //组装导出对象
            exportTableBean.setTitle("Export Error List");
            exportTableBean.setHeaders(Arrays.asList("序号","编号","类名","方法名","扣除分值","规则类型","错误信息"));
            exportTableBean.setKeys(Arrays.asList("headers.size-1","code","javaClass","javaMethod","score","ruleset","describe"));
            exportTableBean.setWidth(Arrays.asList(4,5,28,28,4,30,85));

            List<Map<String, Object>> rowMaps = BeanKit.EntityConvertMap(deductions);
            exportTableBean.setDataList(rowMaps);

            ExportExcelUtil.exportExcel(exportTableBean,out);
            out.close();
            //弹出导出的文件夹目录,并默认选中
            Runtime.getRuntime().exec("explorer /select, " + exportFile.getPath());
            LOGGER.info("导出成功");
        }catch (Exception ex){
            LOGGER.info("导出Excel出错:" + ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void execScanService(ProgressIndicator indicator){

        /* 获取ip段列表 */
        String startIp = startIpInput.getText();
        String endIp = endIpInput.getText();
        String[] startIpSplit = startIp.split("\\.");
        String[] endIpSplit = endIp.split("\\.");
        Integer num = Integer.valueOf(endIpSplit[3]) - Integer.valueOf(startIpSplit[3]);
        List<String> ips=new ArrayList<String>();
        for(int i=0;i<=num;i++){
            ips.add(startIpSplit[0]+"."+startIpSplit[1]+"."+startIpSplit[2]+"."+(Integer.valueOf(startIpSplit[3])+i));
        }
        /* 获取IP段 */
        List<String> portList = Arrays.asList(portInput.getText().split("\\,"));
        List<ScanResult> scanResults = new ArrayList<ScanResult>();
        for(int i=0;i<ips.size();i++){
            for(int j=0;j<portList.size();j++){
                ScanResult scanResult = new ScanResult();
                scanResult.setIp(ips.get(i));
                scanResult.setPort(Integer.valueOf(portList.get(j)));
                scanResults.add(scanResult);
            }
        }


        /* 设置单击事件 */
        ipResultTable.addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent e){
                if(e.getClickCount() == 1){
                    //实现双击 {
                    int row =((JTable)e.getSource()).rowAtPoint(e.getPoint()); //获得行位置
                    int  col=((JTable)e.getSource()).columnAtPoint(e.getPoint());
                    //获得列位置
                    TableModel tbModel = ipResultTable.getModel();
//                    Object cellVal=(String)(tbModel.getValueAt(row,col));
                    // 获得点击单元格数据
                    ScanResult scanResult = scanResults.get(row);
                    if(scanResult.getIsDhg()){
                        // 调用电脑浏览器打开DHG代码规范的页面
                        String url = "http://"+scanResult.getIp()+":"+scanResult.getPort();
                        try {
                            Runtime.getRuntime().exec("cmd /c start " + url);//启用cmd运行默认浏览器
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }else{
                        Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
                        HintManager.getInstance().showErrorHint(editor,"这个地址没有服务可用");
                    }
                }
            }
        });

        /* 将结果渲染到UI界面 */
        Object[][] rowData=new Object[scanResults.size()][];
        for(int i=0;i<scanResults.size();i++){
            ScanResult scanResult=scanResults.get(i);
            System.out.println("正在测试连接"+scanResult.getIp()+":"+scanResult.getPort());
            indicator.setText("正在测试连接"+scanResult.getIp()+":"+scanResult.getPort());
            indicator.setText("正在处理连接："+scanResult.getIp()+":"+scanResult.getPort());
//            Boolean connect = NetUtil.connect(scanResult.getIp(), scanResult.getPort());
            String result = NetUtil.sendUrlRequest("http://" + scanResult.getIp() + ":" + scanResult.getPort());
            if(result!=null){
                scanResult.setResult("ok");
                /* 调用获取版本号的接口 */
                String versionResult = NetUtil.sendMessage("http://" + scanResult.getIp() + ":" + scanResult.getPort()+"/sysVersion/get");
                if(versionResult!=null){
                    /* 检测是否是DHG */
                    scanResult.setIsDhg(true);
                    /* 检测是DHG的哪个分支 */
                    scanResult.setBranch(JSONUtil.parseObj(versionResult).get("data").toString());
                }else{
                    scanResult.setIsDhg(true);
                    scanResult.setBranch(versionResult);
                }
            }else{
                scanResult.setResult("error");
                scanResult.setIsDhg(false);
            }
            rowData[i]=new Object[]{
                    scanResult.getIp(),
                    scanResult.getPort(),
                    scanResult.getResult(),
                    scanResult.getIsDhg(),
                    scanResult.getBranch()
            };
            TableModel dataModel = new DefaultTableModel(rowData,ipColumnNames);
            ipResultTable.setModel(dataModel);
        }
    }

    public DHGToolWindow(boolean vertical) {
        super(vertical);
    }

    public DHGToolWindow(boolean vertical, boolean borderless) {
        super(vertical, borderless);
    }



    public void refreshPluginErrorInfos (List<PluginModueExamInfo> examInfoDeductions){
        /* 渲染行数据 */
        pluginModuledeductions = examInfoDeductions;
        Object[][] rowData=new Object[examInfoDeductions.size()][];
        for(int i=0;i<examInfoDeductions.size();i++){
            PluginModueExamInfo awardedInfo = examInfoDeductions.get(i);
            rowData[i]=new Object[]{
                    awardedInfo.getModuleName(),
                    awardedInfo.getFileName(),
                    awardedInfo.getDesc(),
                    awardedInfo.getSuggest()
            };
        };
        TableModel dataModel = new DefaultTableModel(rowData,pluginColumnNames);
        pluginModuleTable.setModel(dataModel);
    }


    public void refreshErrorInfos(CodeScoreInfo codeScoreInfo){
        /* 渲染行数据 */
        deductions = codeScoreInfo.getDeduction();
        Object[][] rowData=new Object[deductions.size()][];
        for(int i=0;i<deductions.size();i++){
            AwardedInfo awardedInfo = deductions.get(i);
            rowData[i]=new Object[]{
                    awardedInfo.getCode(),
                    awardedInfo.getJavaClass(),
                    awardedInfo.getJavaMethod(),
                    awardedInfo.getScore(),
                    awardedInfo.getRuleset(),
                    awardedInfo.getDescribe()
            };
        };
        TableModel dataModel = new DefaultTableModel(rowData,columnNames);
        codeErrorTable.setModel(dataModel);
    }
    public void skipCodeInfo(){
        /* 跳转到代码异常检测标签 */
        mainTab.setSelectedIndex(1);


    }

    /**
     * 处理HTML中的点击超链接事件
     * */
    @Override
    public void hyperlinkUpdate(HyperlinkEvent e) {

    }
}
